﻿#include "Chatroom.h"
#include "tcp.h"
#include "./ui_Chatroom.h"
#include <QMessageBox>
#include <QDateTime>
#include "client.h"
Chatroom::Chatroom(QString name, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Chatroom)
    , broadcastTimer(new QTimer(this)),updatelistTimer(new QTimer(this))
{
    ui->setupUi(this);
    this->port = 3508;
    this->udpSocket = new QUdpSocket(this);
    this->tcpServer = new QTcpServer(this);
    udpSocket->bind(this->port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
    setName(name);
    online_users = 0;
    //获取当前IP
    uIP = getIP();
    //监听信号
    connect(udpSocket, &QUdpSocket::readyRead, this, &Chatroom::recMessage);

    if(!tcpServer->listen(QHostAddress::Any,6020))
    {
        QMessageBox::warning(this, "提示", "无法开始监听！");
    }
    //连接按钮发送信号
    connect(ui->sendbutton, &QPushButton::clicked,this,[=](){sndMessage(sndmsg);});
    //连接定时器到广播
    connect(broadcastTimer, &QTimer::timeout, this, [=](){sndMessage(online_broadcast);});
    //连接定时器到用户列表更新
    connect(broadcastTimer, &QTimer::timeout, this, &Chatroom::updateUserList);
    // 连接双击事件到槽函数
    connect(ui->userlist, &QListWidget::itemDoubleClicked, this, &Chatroom::onUserItemDoubleClicked);
    //连接小窗开启到TCP连接事件
    connect(tcpServer, &QTcpServer::newConnection, this, &Chatroom::newConnection_Slot);
    //设置定时器
    broadcastTimer->start(500);
    updatelistTimer->start(1000);
    //发送上线通知
    sndMessage(user_enter);
}

Chatroom::~Chatroom()
{
    sndMessage(user_left);

    //处理udp
    udpSocket->flush();  // 确保所有数据已写入缓冲区
    QThread::msleep(100);
    delete udpSocket;

    //处理tcp
    // 先关闭所有客户端连接
    for (QTcpSocket *clientSocket : clientSockets)
    {
        if (clientSocket && (clientSocket->state() == QAbstractSocket::ConnectedState))
        {
            clientSocket->disconnectFromHost();  // 断开连接
            if (clientSocket->state() != QAbstractSocket::UnconnectedState)
            {
                clientSocket->waitForDisconnected();  // 等待客户端完全断开
            }
            clientSocket->deleteLater();  // 安全删除 socket
        }
    }

    // 关闭服务器，停止接受新连接
    tcpServer->close();

    delete ui;
}
void Chatroom::newConnection_Slot()   //连接槽函数
{
    QTcpSocket *newSocket = tcpServer->nextPendingConnection();

    if (newSocket)
    {
        // 创建聊天对话框
        Tcp *chatDialog = new Tcp(newSocket,this->uname);
        chatDialog->show();
        clientSockets.append(newSocket);
    }
}


void Chatroom::on_bt_yes_clicked()
{
    QMessageBox::warning(this, "WARNING", "YOLO");
}

void Chatroom::setName(QString name)
{
    this->uname = name;
}

QString Chatroom::getName()
{
    return this->uname;
}

QString Chatroom::getMsg()
{
    QString msg = ui->msgtextEdit->toHtml();
    ui->msgtextEdit->clear();
    ui->msgtextEdit->setFocus();
    return msg;
}

QString Chatroom::getIP()
{
    QString localIP;
    QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
    for(auto address : addresses)
    {
        if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress::Null && address != QHostAddress::LocalHost)
        {
            localIP = address.toString();
            break;
        }
    }
    return localIP;
}

quint16 Chatroom::getPort()
{
    return this->port;
}

uint8_t Chatroom::sndMessage(Chatroom::Msgtype msg_type)
{
    QByteArray snd_array;
    QDataStream stream(&snd_array, QIODevice::WriteOnly);
    stream<<msg_type<<this->getName()<<this->uIP<<this->port;
    switch(msg_type)
    {
    case sndmsg:
        if(ui->msgtextEdit->toPlainText()=="")
        {
            QMessageBox::warning(this, "提示", "内容不能为空");
            return 0;
        }
        stream<<this->getMsg();
        break;
    case user_enter:
        break;
    case user_left:
        break;
    case online_broadcast:
        break;
    }
    //书写报文
    udpSocket->writeDatagram(snd_array.data(),snd_array.size(),QHostAddress::Broadcast, this->port);

    return 1;
}

void Chatroom::recMessage()
{
    qint64 msg_size = udpSocket->pendingDatagramSize();
    int size = static_cast<int>(msg_size);
    QByteArray msg_array =QByteArray(size,0);
    udpSocket->readDatagram(msg_array.data(),size);
    QDataStream stream(&msg_array,QIODevice::ReadOnly);
    Chatroom::Msgtype msg_type;
    stream>>msg_type;
    QString name,IP,msg;
    quint16 port;
    QString time =QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    stream>>name>>IP>>port;
    Userinfo snduser(name,IP,port);
    snduser.lastinfotime = QTime::currentTime();
    switch (msg_type)
    {
    case sndmsg: //普通聊天文本
        stream>>msg;//流出消息
        ui->msgbrowser->setTextColor(QColor(Qt::blue));
        ui->msgbrowser->append("["+name+"]于"+time);
        ui->msgbrowser->setTextColor(QColor(Qt::black));
        ui->msgbrowser->append(msg);
        break;
    case user_enter: //用户上线
        userlist.append(snduser);
        ui->msgbrowser->setTextColor(QColor(210,105,30));
        ui->msgbrowser->append("["+name+"]于"+time+"上线");
        addUserToList(snduser);
        break;
    case user_left:{ //用户离线
        int pos = userlist.indexOf(snduser);
        if(pos != -1)
        {
            userlist.removeAt(pos);
        }
        ui->msgbrowser->setTextColor(QColor(210,105,30));
        ui->msgbrowser->append("["+name+"]于"+time+"下线");
        break;
    }
    case online_broadcast:
        snduser.lastinfotime = QTime::currentTime();
        addUserToList(snduser);
        break;
    }
}

void Chatroom::addUserToList(const Userinfo &user)
{
    //检查有无离线用户
    for (Userinfo &u : userlist)
    {
        if(u == user)
        {
            u.lastinfotime = user.lastinfotime;
        }

        if(u.lastinfotime.secsTo(QTime::currentTime()) > 3) //认为用户已下线
        {
            userlist.removeOne(u);
            ui->msgbrowser->setTextColor(QColor(210,105,30));
            ui->msgbrowser->append("["+ u.username +"]于"+ QTime::currentTime().toString()+ "下线");
        }
    }

    // 检查用户是否已经存在列表中
    for (const Userinfo &u : userlist)
    {
        if (u.username == user.username && u.userIP == user.userIP)
        {
            return;  // 用户已经存在
        }
    }
    userlist.append(user);
}

void Chatroom::updateUserList()
{
    ui->userlist->clear();
    for (const Userinfo &user : userlist) {
        QListWidgetItem *item = new QListWidgetItem(user.username);
        item->setData(Qt::UserRole + 1, user.userIP);
        item->setData(Qt::UserRole + 2, user.userport);

        item->setData(Qt::DisplayRole, user.username);
        ui->userlist->addItem(item);
    }
}

void Chatroom::onUserItemDoubleClicked(QListWidgetItem *item)
{
    //QMessageBox::warning(this, "提示", item->text());
    QString userIP = item->data(Qt::UserRole + 1).toString();
    QString userID = item->data(Qt::DisplayRole).toString();
    Client *tcpclient = new Client(userIP,userID,this->uname);
    tcpclient->show();
}

